<?php
/**
 * Created by JetBrains PhpStorm.
 * User: dodasso
 * Date: 7/21/13
 * Time: 9:15 PM
 * To change this template use File | Settings | File Templates.
 */

namespace persistance;

require_once(APP_ROOT . '/modules/log/log.php');
require_once(APP_ROOT . '/modules/log/logCommon.php');
require_once(APP_ROOT . '/modules/persistance/DBConnector.php');
require_once(APP_ROOT . '/modules/common/Errors.php');
require_once(APP_ROOT . '/modules/session/SessionDto.php');

use \PDO;
use log\Log;
use log\LogCommon;
use persistance\DBConnector;
use common\Errors;
use session\SessionDto;

class SessionPersistance {
    /**
     * @var DBConnector
     */
    private $db;

    /**
     * @var boolean
     */
    private $initialized;

    public function __construct() {
        $this->db          = null;
        $this->initialized = false;
    }

    public function __destruct() {
    }

    public function init($db) {
        if((is_null($db)) || !($db instanceof DBConnector)) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeError, "Invalid parameters.");
            return false;
        }

        $this->db          = $db;
        $this->initialized = true;

        return true;
    }

    /**
     * @param $rsa array
     * @return null|SessionDto
     */
    private function sessionFromStatementResult($rsa) {
        if((is_null($rsa)) || (count($rsa) != 1)) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeError, "Invalid parameters.");
            return null;
        }

        $rs = $rsa[0];
        $obj                  = new SessionDto();
        $obj->id              = intval($rs['id']);
        $obj->key             = $rs['key'];
        $obj->userId          = intval($rs['user_id']);
        $obj->createdAt       = $rs['created_at'];
        $obj->updatedAt       = $rs['updated_at'];
        $obj->remoteAddresses = $rs['remote_addresses'];
        $obj->userAgent       = $rs['user_agent'];

        return $obj;
    }

    /**
     * @param $session SessionDto
     * @return array
     */
    public function createSession($session) {
        if((is_null($session)) ||
           (!is_null($session->id))) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeError, "Invalid parameters.");
            return array('error'=>ERRORS::INTEGRAL_ERR_INVALID_PARAMETERS);
        }

        if((!$this->initialized)) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeError, "Not initialized.");
            return array('error'=>ERRORS::INTEGRAL_ERR_PERSISTANCE_NOT_INITIALIZED);
        }

        if((!$this->db->isConnected())) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeError, "Not connected to DB.");
            return array('error'=>ERRORS::INTEGRAL_ERR_PERSISTANCE_NOT_CONNECTED);
        }

        $query = 'INSERT INTO session ' .
                 '(`key`, user_id, remote_addresses, user_agent)' .
                 'VALUES ' .
                 '(?, ?, ?, ?)';

        $this->db->insert($query,
            array(array($session->key, PDO::PARAM_STR, 40),
                  array($session->userId, PDO::PARAM_INT, null),
                  array($session->remoteAddresses, PDO::PARAM_STR, 256),
                  array($session->userAgent, PDO::PARAM_STR, 512)));

        if($this->db->lastDBErrorCode() != null) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeCritical, 'Unable to execute insert. ' .
                 implode(' ', $this->db->lastDBErrorInfo()));
            return array('error'=>Errors::INTEGRAL_ERR_PERSISTANCE_UNABLE_TO_CREATE);
        }

        $rs = $this->findByKey($session->key);
        if($rs['error'] != Errors::INTEGRAL_ERR_NONE) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeCritical, 'Session not found. Key: ' . $session->key);
            return array('error'=>Errors::INTEGRAL_ERR_PERSISTANCE_UNABLE_TO_MAP_OBJECT);
        }

        return array('error'=>Errors::INTEGRAL_ERR_NONE, 'data'=>$rs['data']);
    }

    /**
     * @param $session SessionDto
     * @return array
     */
    public function deleteSession($session) {
        if((is_null($session)) ||
           (is_null($session->id))) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeError, "Invalid parameters.");
            return array('error'=>ERRORS::INTEGRAL_ERR_INVALID_PARAMETERS);
        }

        if((!$this->initialized)) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeError, "Not initialized.");
            return array('error'=>ERRORS::INTEGRAL_ERR_PERSISTANCE_NOT_INITIALIZED);
        }

        if(!$this->db->isConnected()) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeError, "Not connected to DB.");
            return array('error'=>ERRORS::INTEGRAL_ERR_PERSISTANCE_NOT_CONNECTED);
        }

        $query = 'DELETE FROM session ' .
                 'WHERE id = ?';
        $rs = $this->db->delete($query,
            array(array($session->id, PDO::PARAM_INT, null)));

        if($this->db->lastDBErrorCode() != null) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeCritical, 'Unable to execute delete. Id: ' .
                $session->id . '. ' . implode(' ', $this->db->lastDBErrorInfo()));
            return array('error'=>Errors::INTEGRAL_ERR_PERSISTANCE_UNABLE_TO_DELETE);
        }

        if((is_null($rs)) || ($rs == 0)) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeCritical, 'Unable to execute delete. Id: ' .
                $session->id);
            return array('error'=>Errors::INTEGRAL_ERR_PERSISTANCE_UNABLE_TO_DELETE);
        }

        return array('error'=>Errors::INTEGRAL_ERR_NONE);
    }

    /**
     * @param $user User
     * @return array
     */
    public function deleteSessionsOfUser($user) {
        if((is_null($user)) ||
            (is_null($user->id))) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeError, "Invalid parameters.");
            return array('error'=>ERRORS::INTEGRAL_ERR_INVALID_PARAMETERS);
        }

        if((!$this->initialized)) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeError, "Not initialized.");
            return array('error'=>ERRORS::INTEGRAL_ERR_PERSISTANCE_NOT_INITIALIZED);
        }

        if(!$this->db->isConnected()) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeError, "Not connected to DB.");
            return array('error'=>ERRORS::INTEGRAL_ERR_PERSISTANCE_NOT_CONNECTED);
        }

        $query = 'DELETE FROM session' .
                 ' WHERE user_id = ?';
        $rs = $this->db->delete($query,
            array(array($user->id, PDO::PARAM_INT, null)));

        if($this->db->lastDBErrorCode() != null) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeCritical, 'Unable to execute delete. ' .
                implode(' ', $this->db->lastDBErrorInfo()));
            return array('error'=>Errors::INTEGRAL_ERR_PERSISTANCE_UNABLE_TO_DELETE);
        }
        if(is_null($rs)) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeCritical, 'Unable to execute delete.');
            return array('error'=>Errors::INTEGRAL_ERR_PERSISTANCE_UNABLE_TO_DELETE);
        }

        return array('error'=>Errors::INTEGRAL_ERR_NONE);
    }

    /**
     * @param $key string
     * @return array
     */
    public function findByKey($key) {
        if((is_null($key)) || (!is_string($key))) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeError, "Invalid parameters.");
            return array('error'=>ERRORS::INTEGRAL_ERR_INVALID_PARAMETERS);
        }

        if((!$this->initialized)) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeError, "Not initialized.");
            return array('error'=>ERRORS::INTEGRAL_ERR_PERSISTANCE_NOT_INITIALIZED);
        }

        if(!$this->db->isConnected()) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeError, "Not connected to DB.");
            return array('error'=>ERRORS::INTEGRAL_ERR_PERSISTANCE_NOT_CONNECTED);
        }

        $query = 'SELECT *' .
                 ' FROM session' .
                 ' WHERE `key` = ?';
        $rsa = $this->db->query($query,
            array(array($key, PDO::PARAM_STR, 40)));

        if($this->db->lastDBErrorCode() != null) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeCritical, 'Unable to execute query. '
                . implode(' ', $this->db->lastDBErrorInfo()));
            return array('error'=>Errors::INTEGRAL_ERR_PERSISTANCE_UNABLE_TO_READ);
        }

        if((is_null($rsa)) || (empty($rsa))) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeNotice, 'Session not found. Key: ' .
                $key);
            return array('error'=>Errors::INTEGRAL_ERR_PERSISTANCE_NOT_FOUND);
        }

        $obj = $this->sessionFromStatementResult($rsa);
        if(is_null($obj)) {
            Log::LOG_PERSISTANCE(LogCommon::logTypeNotice, 'Unable to map session. Key: ' .
                $key);
            return array('error'=>Errors::INTEGRAL_ERR_PERSISTANCE_UNABLE_TO_MAP_OBJECT);
        }

        return array('error'=>Errors::INTEGRAL_ERR_NONE, 'data'=>$obj);
    }
}